package com.cskaoyan.duolai.clean.housekeeping.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cskaoyan.duolai.clean.common.expcetions.ForbiddenOperationException;
import com.cskaoyan.duolai.clean.common.model.dto.PageDTO;
import com.cskaoyan.duolai.clean.housekeeping.converter.RegionServeConverter;
import com.cskaoyan.duolai.clean.housekeeping.dto.*;
import com.cskaoyan.duolai.clean.housekeeping.enums.HousekeepingStatusEnum;
import com.cskaoyan.duolai.clean.housekeeping.dao.entity.*;
import com.cskaoyan.duolai.clean.housekeeping.dao.mapper.*;
import com.cskaoyan.duolai.clean.housekeeping.request.RegionServeCommand;
import com.cskaoyan.duolai.clean.housekeeping.request.ServePageRequest;
import com.cskaoyan.duolai.clean.housekeeping.service.IHomeService;
import com.cskaoyan.duolai.clean.housekeeping.service.IRegionServeService;
import com.cskaoyan.duolai.clean.mvc.utils.UserContext;
import com.cskaoyan.duolai.clean.mysql.utils.PageUtils;
import com.cskaoyan.duolai.clean.redis.constants.RedisConstants;
import org.bouncycastle.jcajce.provider.symmetric.AES;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务表 服务实现类
 * </p>
 */
@Service
public class RegionServeServiceImpl extends ServiceImpl<RegionServeMapper, RegionServeDO> implements IRegionServeService {

    @Resource
    RegionServeConverter regionServeConverter;

    @Resource
    ServeItemMapper serveItemMapper;

    @Resource
    RegionServeMapper regionServeMapper;

    @Resource
    RegionMapper regionMapper;
    @Resource
    ServeTypeMapper serveTypeMapper;

    @Resource
    ServeSyncMapper serveSyncMapper;


    @Override
    public PageDTO<RegionServeDTO> getPage(ServePageRequest servePageQueryReqDTO) {
        Page<RegionServeDO> regionServeDOPage = new Page<>(
                servePageQueryReqDTO.getPageNo(),
                servePageQueryReqDTO.getPageSize()
        );
        Page<RegionServeDO> regionServeDOIPage = baseMapper.queryRegionServeListByRegionId(
                servePageQueryReqDTO.getRegionId(), regionServeDOPage);
        List<RegionServeDTO> regionServeDTOS = regionServeConverter.regionServeDOsToRegionServeDTOs(regionServeDOIPage.getRecords());
        return PageUtils.toPage(regionServeDOPage, regionServeDTOS);
    }


    @Override
    public void batchAdd(List<RegionServeCommand> regionServeCommandList) {
        // 根据区域id 和 serveItemId 查询RegionServe表中是否已有该服务
        int size = regionServeCommandList.size();
        List<RegionServeDO> regionServeDOS = new ArrayList<>();
        for (int i = 0; i < size; i++) {
            LambdaQueryWrapper<RegionServeDO> regionServeDOWrapper = new LambdaQueryWrapper<>();
            RegionServeCommand regionServeCommand = regionServeCommandList.get(i);
            regionServeDOWrapper.eq(RegionServeDO::getRegionId, regionServeCommand.getRegionId())
                    .eq(RegionServeDO::getServeItemId, regionServeCommand.getServeItemId());
            RegionServeDO regionServeDO = baseMapper.selectOne(regionServeDOWrapper);
            if (regionServeDO == null) {
                //添加RegionServe中
                regionServeDOS.add(regionServeConverter.regionServeCommand2DO(regionServeCommand));
            }
        }


        for (int i = 0; i < regionServeDOS.size(); i++) {
            RegionServeDO regionServeDO = regionServeDOS.get(i);
            RegionDO regionDO = regionMapper.selectById(regionServeDO.getRegionId());
            regionServeDO.setCityCode(regionDO.getCityCode());
            baseMapper.insert(regionServeDO);
        }


    }

    @Override
    @Caching(put = @CachePut(cacheNames = RedisConstants.CacheName.REGION_SERVE_DETAIL, key = "#id"),
            evict = @CacheEvict(cacheNames = RedisConstants.CacheName.FIRST_PAGE_HOT_SERVE, key = "#regionId")
    )
    public RegionServeDetailDTO updatePrice(Long id, Long regionId, BigDecimal price) {
        LambdaQueryWrapper<RegionServeDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(RegionServeDO::getId, id);
        //todo 待检查regionId
        RegionServeDO regionServeDO = baseMapper.selectOne(queryWrapper);
        regionServeDO.setPrice(price);
        baseMapper.updateById(regionServeDO);


        RegionServeDetailDTO regionServeDetailDTO = new RegionServeDetailDTO();
        regionServeDetailDTO.setRegionId(regionId);
        regionServeDetailDTO.setPrice(price);

        // 更新价格时需要更新同步表中的数据
        RegionServeSyncDO regionServeSyncDO = serveSyncMapper.selectById(id);
        regionServeSyncDO.setPrice(price);
        serveSyncMapper.updateById(regionServeSyncDO);

        return regionServeDetailDTO;
    }

    @Override
    @CachePut(cacheNames = RedisConstants.CacheName.FIRST_PAGE_HOT_SERVE, key = "#regionId")
    public List<RegionServeDetailDTO> changeHotStatus(Long id, Long regionId, Integer flag) {
        LambdaQueryWrapper<RegionServeDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(RegionServeDO::getId, id);

        RegionServeDO regionServeDO = baseMapper.selectOne(queryWrapper);
        if (regionServeDO == null) {
            throw new ForbiddenOperationException("");
        }
        if (regionServeDO.getSaleStatus() != 2) {
            throw new ForbiddenOperationException("");
        }
        regionServeDO.setIsHot(flag);
        baseMapper.updateById(regionServeDO);


        return findHotServeListByRegionId(regionServeDO.getRegionId());
    }

    /**
     * 根据区域id和状态查询区域上架的服务数量
     *
     * @param regionId   区域id
     * @param saleStatus 状态，0：草稿，1下架，2上架。可传null，即查询所有状态
     * @return 服务数量
     */
    @Override
    public int queryServeCountByRegionIdAndSaleStatus(Long regionId, Integer saleStatus) {
        LambdaUpdateWrapper<RegionServeDO> queryWrapper = Wrappers.<RegionServeDO>lambdaUpdate()
                .eq(RegionServeDO::getRegionId, regionId)
                .eq(RegionServeDO::getSaleStatus, saleStatus);

        return Math.toIntExact(baseMapper.selectCount(queryWrapper));
    }

    @Override
    public int queryServeCountByServeItemIdAndSaleStatus(Long serveItemId, Integer saleStatus) {

        return 0;
    }

    @Override
    public void deleteById(Long id) {
        RegionServeDO regionServeDO = baseMapper.selectById(id);
        if (regionServeDO == null) {
            throw new ForbiddenOperationException();
        }
        if (regionServeDO.getSaleStatus() != 0) {
            throw new ForbiddenOperationException("当前的服务不是草稿类型");
        }
        baseMapper.deleteById(id);

    }

    @Override
    @Cacheable(cacheNames = RedisConstants.CacheName.REGION_SERVE_DETAIL, key = "#id")
    public RegionServeDetailDTO findDetailByIdCache(Long id) {
        RegionServeDetailDTO detailByIdDb = findDetailByIdDb(id);
        if (detailByIdDb == null) {
            return new RegionServeDetailDTO();
        }
        return detailByIdDb;
    }

    public RegionServeDetailDTO findDetailByIdDb(Long id) {
        RegionServeDO regionServeDO = regionServeMapper.selectById(id);
        RegionDO regionDO = regionMapper.selectById(regionServeDO.getRegionId());
        if (HousekeepingStatusEnum.DISABLE.getStatus() == regionDO.getActiveStatus()) {
            return new RegionServeDetailDTO();
        }

        RegionServeDetailDO regionServeDetail = baseMapper.findRegionServeDetail(id);

        return regionServeConverter.regionServeDetailDO2DTO(regionServeDetail);
    }

    @Autowired
    IHomeService iHomeService;

    @CachePut(cacheNames = RedisConstants.CacheName.FIRST_PAGE_PARTIAL_SERVE_CACHE, key = "#regionId")
    @Override
    public List<ServeTypeHomeDTO> refreshFirstPageRegionServeList(Long regionId) {
        return iHomeService.queryServeIconCategoryByRegionIdDb(regionId);
    }

    @CachePut(cacheNames = RedisConstants.CacheName.REGION_SERVE_DETAIL, key = "#regionId")
    @Override
    public List<RegionServeDetailDTO> refreshFistPageHotServeList(Long regionId) {
        return findHotServeListByRegionId(regionId);
    }

    @CachePut(cacheNames = RedisConstants.CacheName.REGION_SERVE_TYPE, key = "#regionId")
    @Override
    public List<DisplayServeTypeDTO> refreshFirstPageServeTypeList(Long regionId) {
        return iHomeService.queryServeTypeListByRegionIdDb(regionId);
    }

    @Override
    public List<RegionServeDetailDTO> findHotServeListByRegionId(Long regionId) {
        RegionDO regionDO = regionMapper.selectById(regionId);
        if (HousekeepingStatusEnum.DISABLE.getStatus() == regionDO.getActiveStatus()) {
            return Collections.emptyList();
        }
        List<RegionServeDetailDO> hotServeListByRegionId = regionServeMapper.findHotServeListByRegionId(regionId);
        if (hotServeListByRegionId == null) {
            return Collections.emptyList();
        }
        return regionServeConverter.regionServeDetailDOs2DTOs(hotServeListByRegionId);
    }

    @Override
    public List<DisplayServeTypeDTO> findServeTypeListByRegionId(Long regionId) {
        RegionDO regionDO = regionMapper.selectById(regionId);
        if (HousekeepingStatusEnum.DISABLE.getStatus() == regionDO.getActiveStatus()) {
            return Collections.emptyList();
        }
        List<ServeTypeDO> serveTypeListByRegionId = regionServeMapper.findServeTypeListByRegionId(regionId);
        if (serveTypeListByRegionId == null) {
            return Collections.emptyList();
        }
        return regionServeConverter.serveTypeDOsToFirstPageServeTypeDTOs(serveTypeListByRegionId);
    }

    @Override
    @Transactional
    @Caching(evict = {
            @CacheEvict(cacheNames = RedisConstants.CacheName.FIRST_PAGE_PARTIAL_SERVE_CACHE, key = "#result.regionId"),
            @CacheEvict(cacheNames = RedisConstants.CacheName.FIRST_PAGE_HOT_SERVE, key = "#result.regionId"),
            @CacheEvict(cacheNames = RedisConstants.CacheName.REGION_SERVE_TYPE, key = "#result.regionId")
    }, put = {
            @CachePut(cacheNames = RedisConstants.CacheName.REGION_SERVE_DETAIL, key = "#id")
    })
    public RegionServeDetailDTO onSale(Long id) {
        RegionServeDO regionServeDO = baseMapper.selectById(id);
        if (regionServeDO == null) {
            throw new ForbiddenOperationException();
        }
        if (regionServeDO.getSaleStatus() == 2) {
            throw new ForbiddenOperationException("草稿或下架状态方可上架");
        }

        Long serveItemId = regionServeDO.getServeItemId();
        ServeItemDO serveItemDO = serveItemMapper.selectById(serveItemId);
        Integer serveItemDOActiveStatus = serveItemDO.getActiveStatus(); // 获取服务项的启用状态

        if (!(HousekeepingStatusEnum.ENABLE.getStatus() == serveItemDOActiveStatus)) {
            throw new ForbiddenOperationException("服务项为启用状态方可上架");
        }
        ServeTypeDO serveTypeDO = serveTypeMapper.selectById(serveItemDO.getServeTypeId());
        Integer serveTypeDOActiveStatus = serveTypeDO.getActiveStatus();
        if (!(HousekeepingStatusEnum.ENABLE.getStatus() == serveTypeDOActiveStatus)) {
            throw new ForbiddenOperationException("服务类型为启用状态方可上架");
        }
        Long regionId = regionServeDO.getRegionId();
        RegionDO regionDO = regionMapper.selectById(regionId);
        Integer regionDOActiveStatus = regionDO.getActiveStatus();
        if (!(HousekeepingStatusEnum.ENABLE.getStatus() == regionDOActiveStatus)) {
            throw new ForbiddenOperationException("区域为启用状态方可上架");
        }
        // 更新上架状态
        // regionServeDO.setSaleStatus(2);
        // baseMapper.updateById(regionServeDO);
        LambdaUpdateWrapper<RegionServeDO> updateWrapper =
                Wrappers.<RegionServeDO>lambdaUpdate()
                        .eq(RegionServeDO::getId, id)
                        .set(RegionServeDO::getSaleStatus, HousekeepingStatusEnum.ENABLE.getStatus());

        update(updateWrapper);

        // 添加到修改同步表中
        addServeSync(id);
        return findDetailByIdDb(id);
    }

    /**
     * @param serveId 服务id
     */
    private void addServeSync(Long serveId) {
        // 服务信息
        RegionServeDO regionServeDO = baseMapper.selectById(serveId);
        // 区域信息
        RegionDO regionDO = regionMapper.selectById(regionServeDO.getRegionId());

        // 服务项信息
        ServeItemDO serveItemDO = serveItemMapper.selectById(regionServeDO.getServeItemId());

        // 服务类型信息
        ServeTypeDO serveTypeDO = serveTypeMapper.selectById(serveItemDO.getServeTypeId());

        RegionServeSyncDO regionServeSyncDO =
                regionServeConverter.regionServeToServeSyncDO(serveTypeDO, serveItemDO, regionServeDO, regionDO.getCityCode());

        serveSyncMapper.insert(regionServeSyncDO);
    }


    @Override
    @Transactional
    @Caching(evict = {
            @CacheEvict(cacheNames = RedisConstants.CacheName.FIRST_PAGE_PARTIAL_SERVE_CACHE, key = "#result.regionId"),
            @CacheEvict(cacheNames = RedisConstants.CacheName.FIRST_PAGE_HOT_SERVE, key = "#result.regionId"),
            @CacheEvict(cacheNames = RedisConstants.CacheName.REGION_SERVE_TYPE, key = "#result.regionId"),
            @CacheEvict(cacheNames = RedisConstants.CacheName.REGION_SERVE_DETAIL, key = "#id")
    })
    public RegionServeDTO offSale(Long id) {
        RegionServeDO regionServeDO = baseMapper.selectById(id);
        if (regionServeDO == null) {
            throw new ForbiddenOperationException("区域服务不存在");
        }
        if (regionServeDO.getSaleStatus() == 0 || regionServeDO.getSaleStatus() == 1) {
            throw new ForbiddenOperationException();
        }
        regionServeDO.setSaleStatus(1);
        baseMapper.updateById(regionServeDO);
        // 删除同步表中的数据
        serveSyncMapper.deleteById(id);

        return regionServeConverter.regionServeDOToRegionServeDTO(regionServeDO);
    }

    @Override
    public ServeDetailDTO findServeDetailById(Long id) {
        ServeDetailDO serveDetailById = baseMapper.findServeDetailById(id);
        return regionServeConverter.serveDetailDO2DTO(serveDetailById);
    }
}
